﻿#pragma once
using namespace std;
template<class K,class V>
struct AVL_TreeNode
{
	AVL_TreeNode<K, V>*  _left;
	AVL_TreeNode<K, V>*  _right;
	AVL_TreeNode<K, V>*  _parent;

	int _bf;  //balance fector 平衡因子 

	pair <K, V> _kv;

	AVL_TreeNode(const pair<K, V>& kv)
		:_left(nullptr),
		_right(nullptr),
		_parent(nullptr),
		_bf(0),
		_kv(kv)
	{}
};


template<class K, class V>
class AVL_Tree
{
	typedef AVL_TreeNode<K, V> Node;
public:
	AVL_Tree() 
		: _root(nullptr) 
	{}

	bool insert(const pair<K, V>& kv)
	{
		//如果没有节点直接创造节点插入
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;

		//找到插入位置
		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else //重复的
			{
				return false;
			}
		}

		cur = new Node(kv);

		if (parent->_kv.first < kv.first)
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}

		cur->_parent = parent;


		//更新平衡因子
		while (parent)
		{ 
			//如果插入到了右变bf++  平衡因子 = 右子树高度 − 左子树高度
			if (cur == parent->_right)
			{
				parent->_bf++; 
			}
			//插入到了左边bf-- 
			else
			{
				parent->_bf--;
			}


			if (parent->_bf == 0)//说明并没有高度变化可以直接退出
			{
				break;
			}
			else if(parent->_bf==-1|| parent->_bf==1)
			{
				//说明左子树或者右子树存在高度变化需要在往上调整
				cur = parent;
				parent = parent->_parent;
			}
			else if (parent->_bf == -2 || parent->_bf == 2)
			{
				//说明这棵树存在异常需要旋转处理
				// 1.前提是旋转后任然保持他是一颗搜索二叉树
				// 2.旋转成平衡树
				// 3.（插入节点后）旋转后对于parent来说高度没变
				if (parent->_bf == 2)
				{
					if (cur->_bf == 1)
					{
						RotateL(parent);
					}
					else if (cur->_bf == -1)
					{
						//双旋
						RotateRL(parent);
					}
				}
				else if (parent->_bf == -2)
				{
					if (cur->_bf == -1)
					{
						RotateR(parent);
					}
					else if (cur->_bf == 1)
					{
						RotateLR(parent);
					}
				}

				//旋转完成后，parent所在的树的高度回到了，插入节点前的高度
				//如果是子树，对上层没有影响
				break;
			}
		}


		return true;
	}

	//左单旋
	// parent的右边放subR的左边(subR_L)
	// subR的左边放parent  
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subR_L = subR->_left; //subR 的左边
		Node* pphead = parent->_parent;

		parent->_right = subR_L;
		if (subR_L)
			subR_L->_parent = parent;
		
		subR->_left = parent;
		parent->_parent = subR;
		
		//处理subR的父节点
		//1.如果原来的parent是root节点，那么现在把subR当作root root的父节点为null
		if (parent == _root)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else //不是的话就是中间任意一颗树的节点
		{
			subR->_parent = pphead; //pphead就是原来subr的父节点的父节点
			//再判断原来的父节点是pphead左子树还是右子树
			if (pphead->_right == parent)
				pphead->_right = subR;
			else
				pphead->_left = subR;

		}
		parent->_bf = subR->_bf = 0;
	}


	//右单旋
	// parent的左边放subR的右边(subL_R)
	// subR的右边放parent 
	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subL_R = subL->_right;
		Node* pphead = parent->_parent;

		parent->_left = subL_R;
		if (subL_R)
			subL_R->_parent = parent;

		subL->_right = parent;
		parent->_parent = subL;

		//处理subL的父节点
		if (_root == parent)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			subL->_parent = pphead;
			if (pphead->_right == parent)
				pphead->_right = subL;
			else
				pphead->_left = subL;
		}
		parent->_bf = subL->_bf = 0;
	}


	void RotateRL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subR_L = subR->_left;
		int bf = subR_L->_bf;
		RotateR(subR);
		RotateL(parent);

		if (bf == -1)
		{
			parent->_bf = 0;
			subR->_bf = 1;
			subR_L->_bf = 0;
		}
		else if(bf == 1)
		{
			subR->_bf = 0;
			parent->_bf = -1;
			subR_L->_bf = 0; 
		}
		else if (bf == 0)//这种情况是只有三个节点
		{
			parent->_bf = 0;
			subR->_bf = 0;
			subR_L->_bf = 0;
		}

	}

	void RotateLR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subL_R = subL->_right;
		int bf = subL_R->_bf;
		//subL_R（左右双旋里）、subR_L（右左双旋里）是插入节点的 “直接上级”
		//它们的 bf 是 1 还是 - 1，能直接说明插入节点是插在它们的左分支还是右分支
		//（比如 bf=1 就是插右边，bf=-1 就是插左边）。
		RotateL(subL);
		RotateR(parent);

		if (bf == 1)
		{
			parent->_bf = 0;
			subL->_bf = -1;
			subL_R->_bf = 0;
		}
		else if (bf == -1)
		{
			parent->_bf = 1;
			subL->_bf = 0;
			subL_R->_bf = 0;
		}
		else if (bf == 0)
		{
			parent->_bf = 0;
			subL->_bf = 0;
			subL_R->_bf = 0;
		}

	}

	void _InOder(const Node* root)
	{
		if (root == nullptr)
			return;

		_InOder(root->_left);
		cout << root->_kv.first << ":" << root->_kv.second << endl;
		_InOder(root->_right);
	}


	int Height(Node* root)
	{
		if (root == nullptr)
			return 0;

		int left = Height(root->_left);
		int right = Height(root->_right);

		return left > right ? left + 1 : right + 1;
	}

	void InOder()
	{
		_InOder(_root);
		cout << endl;
	}

	bool _IsBlance(Node* root)
	{
		if (root == nullptr)
			return true;
		int leftHeight = Height(root->_left);
		int rightHeight = Height(root->_right);

		return abs(leftHeight - rightHeight) <= 1
			&&_IsBlance(root->_left)
			&&_IsBlance(root->_right);
	}

	bool IsBlance()//和之前的中序遍历一样要创建子函数
	{
		return _IsBlance(_root);
	}

private:
	Node* _root;

};

